import { Card, Scrollbar, Empty, Tag, Pagination, Spin } from "@arco-design/web-vue";
import { TableColumn, TableRecord } from "./types";
import { FunctionalComponent, UnwrapRef } from "vue";
import CustomCheckbox from "./component/CustomCheckbox.vue";
import { get } from "lodash-es";

interface Props {
  loading?: boolean;
}

type UseTableReturn<T> = [
  FunctionalComponent<Props>,
  {
    checkedRecords: ComputedRef<UnwrapRef<T>[]>;
    setTableData: (rawRecords: any[]) => void;
    setCheckboxVisible: (visible: boolean) => void;
  }
];

export default function useTable<T = any>(tableColumns: TableColumn<T>[]): UseTableReturn<T> {
  let windowListener: any = null;
  const windowHeight = ref(window.innerHeight);
  const showCheckbox = ref(false);
  const tableData = ref<TableRecord<T>[]>([]);
  const pagination = reactive({
    pageNo: 1,
    pageSize: 10,
  });
  const checkedRecords = computed(() => unref(tableData).filter((record) => record.isChecked));
  const checkedRawRecords = computed(() => checkedRecords.value.map((record) => record.rawRecord));
  const isCheckedAllNow = computed(() => unref(checkedRecords).length == unref(tableData).length);

  const handleCheckAll = () => {
    if (!unref(showCheckbox)) return;
    const checkedAll = unref(isCheckedAllNow);
    unref(tableData).forEach((record) => (record.isChecked = !checkedAll));
  };

  const setTableData = (rawRecords: T[]) => {
    const data = rawRecords.map((record) => {
      return {
        isChecked: false,
        rawRecord: record,
      } as TableRecord;
    });
    tableData.value = data;
  };

  const setCheckboxVisible = (visible: boolean) => {
    showCheckbox.value = visible;
  };

  const TableEmpty = () => {
    return (
      <Card bordered={false}>
        <Empty />
      </Card>
    );
  };

  const TableNotEmpty = defineComponent({
    props: {
      loading: Boolean,
    },
    setup(props) {
      const cls = `flex-y-center h-14 guat-card cursor-pointer`;
      const Cell: FunctionalComponent<{
        col: TableColumn;
        record: any;
      }> = ({ col, record }) => {
        const tdStyle = {
          class: `h-1 first:rounded-tl-lg first:rounded-bl-lg last:rounded-tr-lg last:rounded-br-lg last:pr-4`,
          style: { width: col.width ? `${col.width}px` : undefined },
        };
        const Comp = col.render?.(record)! as FunctionalComponent;
        return (
          <td {...tdStyle}>
            <div class="flex flex-col items-center p-4 h-full">
              {col.title && <div class="h-4 select-none text-tc-3">{col.title}</div>}
              <div class={`flex flex-1 items-center ${col.title ? "pt-2" : ""}`}>
                {col.dataIndex && <span class="text-base">{get(record, col.dataIndex)}</span>}
                {col.render && <Comp />}
              </div>
            </div>
          </td>
        );
      };
      onMounted(() => {
        window.addEventListener(
          "resize",
          (windowListener = () => {
            windowHeight.value = window.innerHeight;
          })
        );
      });
      onUnmounted(() => {
        windowListener && window.removeEventListener("resize", windowListener);
      });
      return () => (
        <div>
          <Scrollbar class="overflow-auto" style={{ maxHeight: `${unref(windowHeight) - 224}px` }}>
            <Spin dot loading={props.loading} class="w-full">
              <table class="w-full mt-[-32px] border-separate border-spacing-y-4">
                <tbody class="relative bottom-[-16px]">
                  {unref(tableData).map((record) => {
                    const tdStyle = "w-20 pl-8 first:rounded-tl-lg first:rounded-bl-lg";
                    return (
                      <tr class="bg-bg-3">
                        {unref(showCheckbox) && (
                          <td class={tdStyle}>
                            <CustomCheckbox
                              checked={record.isChecked}
                              onUpdate:checked={(value) => (record.isChecked = value)}
                            />
                          </td>
                        )}
                        {unref(tableColumns).map((col) => (
                          <Cell col={col} record={record.rawRecord} />
                        ))}
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </Spin>
          </Scrollbar>
          <div class="flex-xb-yc mt-4">
            <div class="flex gap-4">
              {!showCheckbox.value ? (
                <div class={cls} onClick={() => (showCheckbox.value = true)}>
                  开启复选框
                </div>
              ) : (
                <>
                  <div class="flex-y-center text-base guat-card">
                    当前已选中
                    <Tag class="mx-2" color="blue">
                      {unref(checkedRecords).length}
                    </Tag>
                    条记录
                  </div>
                  <div class={cls} onClick={handleCheckAll}>
                    <span>{unref(isCheckedAllNow) ? "取消全选" : "全选"}</span>
                  </div>
                  <div class={cls} onClick={() => (showCheckbox.value = false)}>
                    关闭复选框
                  </div>
                </>
              )}
            </div>
            <div class="guat-card py-[10px]">
              <Pagination
                size="large"
                total={unref(tableData).length}
                current={pagination.pageNo}
                pageSize={pagination.pageSize}
                show-total
                show-jumper
                show-page-size
                onUpdate:current={(v) => (pagination.pageNo = v)}
                onUpdate:pageSize={(v) => (pagination.pageSize = v)}
              />
            </div>
          </div>
        </div>
      );
    },
  });

  const CustomTable: FunctionalComponent<Props> = (props) => {
    return unref(tableData).length == 0 ? <TableEmpty /> : <TableNotEmpty {...props} />;
  };

  return [
    CustomTable,
    {
      setTableData,
      setCheckboxVisible,
      checkedRecords: checkedRawRecords as any,
    },
  ];
}
